package com.atguigu.rabbitmq.three;

import com.atguigu.rabbitmq.util.RabbitmqUtil;
import com.atguigu.rabbitmq.util.SleepUtil;
import com.rabbitmq.client.Channel;

import java.io.IOException;
import java.util.Map;

/**
 * @author codingBee
 * @since 2021/6/22/21:24
 * 测试消息在手动应答时是不丢失的，当信道由于异常断开连接时，会将未消费的消息重新放回队列。从而保证消息不丢失
 */
public class Work02 {
    //队列名称
    public static final String TASK_QUEUE_NAME = "ack_queue";

    public static void main(String[] args) throws IOException {
        Channel chanel = RabbitmqUtil.getChannel();
        /**
         * Request a specific prefetchCount "quality of service" settings
         * for this channel.
         * @see #basicQos(int, int, boolean)
         * @param prefetchCount maximum number of messages that the server 预期值
         * will deliver, 0 if unlimited 服务器读取的最大消息数，如果为0，那么就是无限制，如果是1的话
         * @throws java.io.IOException if an error is encountered
         */
        chanel.basicQos(2);
        System.out.println("C1等待接收消息处理，短时间");
        /**
         * Start a non-nolocal, non-exclusive consumer, with
         * a server-generated consumerTag. 创建一个消费者
         * Provide access only to <code>basic.deliver</code> and
         * <code>basic.cancel</code> AMQP methods (which is sufficient
         * for most cases). See methods with a {@link com.rabbitmq.client.Consumer} argument
         * to have access to all the application callbacks.
         * @param queue the name of the queue 队列名称
         * @param autoAck true if the server should consider messages
         * acknowledged once delivered; false if the server should expect
         * explicit acknowledgements 是否自动应答
         * @param deliverCallback callback when a message is delivered 消息传递时的回调
         * @param cancelCallback callback when the consumer is cancelled 当消费者被取消的回调
         * @return the consumerTag generated by the server 由服务器生成的消费者标签
         * @throws IOException if an error is encountered
         * @see com.rabbitmq.client.AMQP.Basic.Consume
         * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk
         * @see #basicAck
         * @see #basicConsume(String, boolean, String, boolean, boolean, Map, com.rabbitmq.client.Consumer)
         * @since 5.0
         */
        chanel.basicConsume(TASK_QUEUE_NAME, Boolean.FALSE, (consumerTag, message) -> {
            System.out.println(String.format("消息被接收 consumerTag:[%s]\tmessage:[%s]", consumerTag, new String(message.getBody())));
            SleepUtil.sleep(1);
            /**
             * Acknowledge one or several received
             * messages. Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk} 显示应答消息
             * or {@link com.rabbitmq.client.AMQP.Basic.Deliver} method
             * containing the received message being acknowledged.
             * @see com.rabbitmq.client.AMQP.Basic.Ack
             * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver} 消息的标记tag
             * @param multiple true to acknowledge all messages up to and 是否批量应答消息
             * including the supplied delivery tag; false to acknowledge just
             * the supplied delivery tag.
             * @throws java.io.IOException if an error is encountered
             */
            chanel.basicAck(message.getEnvelope().getDeliveryTag(), Boolean.FALSE);
            System.out.println("消息被C1应答");

        }, (consumerTag) -> {
            System.out.println(String.format("消息被中断 consumerTag:[%s]", consumerTag));
        });
    }
}
